# vim:ts=4:sw=4:noet:
""" Console Window """

import wx
import wx.stc
from c.ui.wxw.widgets.baseframe import BaseFrame
from c.base.support import CoreException
from editor import DEFAULT_FONT_FACE, DEFAULT_FONT_SIZE
from events import EVT_LOG_ID
import c.compiler.spy as spy

class Console(wx.stc.StyledTextCtrl):

	def __init__(self, parent):
		wx.stc.StyledTextCtrl.__init__(self, parent, -1, wx.DefaultPosition, wx.DefaultSize, 0)

		self.SetMargins(5,5)
		self.SetMarginWidth(1,0)
		self.SetViewWhiteSpace(False)
		self.SetUseAntiAliasing(False)
		self.SetWrapMode(wx.stc.STC_WRAP_WORD)
		self.SetTabWidth(4)
		self.SetCaretWidth(0)
		
		self.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT,	 "face:%s,size:%d" % (
        DEFAULT_FONT_FACE, DEFAULT_FONT_SIZE))
		self.StyleClearAll()
		style = "fore:#cccccc,back:#222222,face:%s,size:%d" % (
        DEFAULT_FONT_FACE, DEFAULT_FONT_SIZE)
		self.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT,	style)
		self.StyleSetSpec(wx.stc.STC_ST_DEFAULT, style)
		
		self.Connect(-1, -1, EVT_LOG_ID, self.logText)

	def logText(self, evt):
		self.SetReadOnly(False)
		if evt.data=="~~clear~~":
			self.ClearAll()
		else:
			self.AppendText(evt.data)
		self.SetReadOnly(True)

	def addText(self, text):
		self.SetReadOnly(False)
		self.AppendText(text)
		self.SetReadOnly(True)

class ConsoleWindow(BaseFrame):
	def __init__(self, parent):
		BaseFrame.__init__(self, parent, "Console", size=(400, 200))
		self.SetMinSize((400,200))
		self.parent = parent
		panel = wx.Panel(self, -1)
		vbox = wx.BoxSizer(wx.VERTICAL)
		self.console = Console(panel) 
		self.entry = wx.TextCtrl(panel, -1, "", style=wx.TE_PROCESS_ENTER)
		self.entry.Bind(wx.EVT_TEXT_ENTER, self.onEnter)
		self.entry.SetFocus()
		vbox.Add(self.console, 1, wx.EXPAND|wx.ALL, -1)
		vbox.Add(self.entry, 0, wx.EXPAND|wx.ALL, -1)
		panel.SetSizer(vbox)
		self.Bind(wx.EVT_CLOSE, self.onClose)
		self.shown = False
		self.Show(self.shown)

	def onDoneRun(self):
		controller = self.parent._controller
		ret = controller.r.getLastReturn()
		self.console.addText("%s\n" % controller.r.getLastReturn().asString())

	def onEnter(self, evt):
		text = self.entry.GetValue()
		self.entry.SetValue("")
		self.console.addText(">> %s\n" % text)
		controller = self.parent._controller
		mcls = controller.mem.getGlobal("mainClass")
		if mcls:
			try:
				spymeth = controller.compiler.compileMethod(
										mcls, "doit [ ^ %s ]" % text)
			except CoreException, e:
				self.console.addText("%s\n" % e)
				return

			methsize = 3+len(spymeth.literals)
			MethodClass = controller.r.getGlobal("Method")
			if not MethodClass:
				print "couldn't get method class"
				return
			rmeth = controller.r.allocObject(methsize, MethodClass.ptr)
			#print "alloced meth", methsize, rmeth
			rmeth.setData(0, controller.r.allocSymbol("doit").ptr)
			rmeth.setData(1, (((spymeth.maxStack<<6)|spymeth.maxTemps)<<2)|2)
			rmeth.setData(2, controller.r.allocByteArray(spymeth.bytecodes).ptr)
			for i, lit in enumerate(spymeth.literals):
				if isinstance(lit, spy.SpySymbol):
					v = lit.optr
				else:
					print "unhandled lit", lit
				rmeth.setData(3+i, v)
			#print "compiled:", mcls.methods.pdict
			controller.r.runMethod(rmeth.ptr, controller.r.getGlobal("mainClass").ptr)
			controller.doRun(self.onDoneRun)

	def show(self):
		self.shown = True
		self.Show()

	def onClose(self, event):
		self.toggleVisible()
	
	def toggleVisible(self):
		self.shown = not self.shown
		self.Show(self.shown)

